﻿using parkMonitor.model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace parkMonitor.server
{
    /// <summary>异步命令服务</summary>
    public class AsyncCmdServer
    {
        public static readonly AsyncCmdServer ins = new AsyncCmdServer();
        public static AsyncCmdServer getInstance() { return ins; }

        object syncObj = new object();
        Dictionary<AsyncCmdType, List<Action>> mapFun = new Dictionary<AsyncCmdType, List<Action>>();
        Dictionary<AsyncCmdType, List<Delegate>> mapFunArgs = new Dictionary<AsyncCmdType, List<Delegate>>();

        public void listen(AsyncCmdType type, Action fun)
        {
            lock (syncObj)
            {
                if (!mapFun.ContainsKey(type))
                {
                    mapFun[type] = new List<Action>();
                }
                mapFun[type].Add(fun);
            }
        }

        public void listen<T>(AsyncCmdType type, Action<T> fun)
        {
            lock (syncObj)
            {
                if (!mapFunArgs.ContainsKey(type))
                {
                    mapFunArgs[type] = new List<Delegate>();
                }
                mapFunArgs[type].Add(fun);
            }
        }

        public void send(AsyncCmdType type)
        {

            List<Action> lstFun = new List<Action>();
            lock (syncObj)
            {
                if (!mapFun.ContainsKey(type))
                {
                    return;
                }

                //lstFun = mapFun[type];
                lstFun = new List<Action>(mapFun[type]);
            }

            Task.Run(() =>
            {
                for (int i = 0; i < lstFun.Count; ++i)
                {
                    lstFun[i].Invoke();
                }
            });
        }

        public void send<T>(AsyncCmdType type, T data)
        {
            List<Delegate> lstFun = new List<Delegate>();
            lock (syncObj)
            {
                if (!mapFunArgs.ContainsKey(type))
                {
                    return;
                }

                lstFun = new List<Delegate>(mapFunArgs[type]);
            }

            Task.Run(() =>
            {
                for (int i = 0; i < lstFun.Count; ++i)
                {
                    Action<T> fun = lstFun[i] as Action<T>;
                    if (fun == null)
                    {
                        continue;
                    }
                    fun.Invoke(data);
                }
            });
        }
    }

    /// <summary>命令类型</summary>
    public enum AsyncCmdType
    {
        /// <summary>
        /// 总状态改变
        /// 参数：AlarmStatus status
        /// </summary>
        TotalStatusChanged,

        /// <summary>
        /// PLC离线
        /// 参数:无
        /// </summary>
        PLCOffline,
        /// <summary>
        /// PLC上线
        /// 参数:无
        /// </summary>
        PLCOnline,
        /// <summary>PLC读异常</summary>
        PLCReadException,
        /// <summary>PLC写异常</summary>
        PLCWriteException,

        /// <summary>号牌机离线</summary>
        //NumMachineOffline,
        /// <summary>号牌机上线</summary>
        //NumMachineOnline,

        /// <summary>Laser1离线</summary>
        Laser1Offline,
        /// <summary>Laser1上线</summary>
        Laser1Online,
        /// <summary>Laser1结算异常</summary>
        Laser1CalcException,
        /// <summary>Laser1系统异常</summary>
        Laser1SystemException,

        /// <summary>Laser2离线</summary>
        Laser2Offline,
        /// <summary>Laser2上线</summary>
        Laser2Online,
        /// <summary>Laser2结算异常</summary>
        Laser2CalcException,
        /// <summary>Laser2系统异常</summary>
        Laser2SystemException
    }
}
